#ifndef _VTXACCUMULATOR_H_
#define _VTXACCUMULATOR_H_

#include "../../utils/fv_assert.h"
#include "BBox3D.h"
#include "fv_inc.h"
#include "RenderParams.h"
#include "MathHelper.h"
#include <string>
#include <vector>

namespace FemViewer {

	class PrimitiveAccumulator;

// Class used to accumulate OpenGL based on a mesh
// (vertices) .  Contains the base data for VertexedPrimitiveAccumulator
//  : vertexes, colors and normals.
// This data may be shared between multiple VertexedPrimitiveAccumulator
class VtxAccumulator
{
public:

  VtxAccumulator ();
  ~VtxAccumulator();
  void  createVBO();
  void  cleanUp();
  void  addColor           (const Vec3D&     pColor);
  void  addVertex          (const Vec3D&     pVertex);
  void  addNode			   (const fvmath::Vec3f& pNode) { 
	  aNodes.push_back(pNode);
	  aBBox += pNode;
  }
  void  addEdge			   (const int s,const int e) {
	  assert(s != e);
	  aIndices.push_back(s);
	  aIndices.push_back(e);
	  ++aEdgeCount;
  }

  void addNodeColor(const fvmath::Vec3f& color) {
	  aNodeColors.push_back(color);
  }

  void addNormal2Node(const fvmath::Vec3f& normal) {
	  aNodeNormals.push_back(normal);
  }

  void addIndexOfNode(const unsigned int index) {
	  aIndices.push_back(index);
  }



  void dumpCharacteristics(std::ostream&       pOstream,
                                            const std::string&  pIndentation,
                                            const Matrix<float>&  pTransformation) const;


  bool  getVerticesFrozen  () const;
  bool  getColorsFrozen    () const;

  bool  freezeColors       ();
  void  freezeVertices     ();

 
  typedef  std::vector<Vec3D>  Colors;
  typedef  std::vector<Vec3D>  Normals;
  typedef  std::vector<Vec3D>  Vertices;
  typedef  fvmath::Vec3f	   NodeCoords;
  typedef  fvmath::Vec3f	   NodeColor;
  typedef  std::vector<NodeCoords> Nodes;
  typedef  std::vector<NodeColor> NodeColors;
  typedef  std::vector<NodeCoords> NodeNormals;
  typedef  Nodes::size_type     NodesSizeType;
  typedef  std::vector<unsigned int> Indices;

  NodeColors& getNodeColors() { return aNodeColors; }

private:

  // Block the use of those
  VtxAccumulator(const VtxAccumulator&);
  VtxAccumulator& operator=(const VtxAccumulator&);

  Colors                 aColors;
  bool                   aColorsFrozen;
  Normals                aNormals;
  bool                   aSimplifiedDirty;
  Vertices               aVertices;
  bool                   aVerticesFrozen;
  Nodes					 aNodes;
  NodeColors			 aNodeColors;
  NodeNormals			 aNodeNormals;
  Indices				 aIndices;
  bool					 aVBOUsed;
  GLuint				 aVBOIds[4];
  BBox3D				 aBBox;
  CVec3f				 aEdgeColor;
  float					 aEdgeThickness;
  unsigned int 			 aEdgeCount;
  
  public:
	bool aRenderEdges;
	bool aRenderTraingleStrips;
	bool aRenderTraingles;
	const Colors& getColors() const;
	const Vertices& getVertices() const;
	const Nodes& getNodes() const { return aNodes; }
	const Indices& getIndices() const { return aIndices; }
	bool& UseVBO() { return aVBOUsed; }
	Normals& getNormals();
	void render(const RenderParams& pPram);
	const BBox3D& getBBox3D() const { return aBBox; }
	void setEdgeColor(const Vec3f& color) { aEdgeColor = color; }
	void setEdgeWidth(const float width) { aEdgeThickness = width; }
  private:
	void renderEdges(const RenderParams& pPr);
	void renderTriangleStrips(const RenderParams& pPr);
	void renderTriangles(const RenderParams& pPr);
};

} // end namespace FemViewer

#endif /* _VTXACCUMULATOR_H_
*/
